package com.landtool.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.landtool.Elasticsearch.TargetChanges;
import com.landtool.Elasticsearch.TgRadarMove;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.*;

@Service
public class IndexerService {
    private static Logger log = LoggerFactory.getLogger(IndexerService.class);

    private final String RADAR_NAME = getRadarName();

    private final String TARGETCHANGES = "targetchanges";

    private static final String TYPE = "_doc";
    //历史所有数据
    private HashMap <String, TargetChanges> eventTable = new HashMap <String, TargetChanges>();
    private TargetChanges item = null;
    private int Time_Second = 120;
    private int Cache_Size = 20000;
    private Calendar calendar = Calendar.getInstance();
    private Iterator <Map.Entry <String, TargetChanges>> entrys = null;

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    /**
     * es批量提交
     *
     * @param ShippingData
     * @return
     */
    public long bulkIndex(String ShippingData)   {
        Integer counter = 0;
        try {
            if (!elasticsearchTemplate.indexExists(RADAR_NAME)) {
                elasticsearchTemplate.createIndex(RADAR_NAME, TgRadarMove.class);
            }
            if (!ShippingData.equals("")) {
                //解析船只数据
                JSONArray ShipArray = JSONUtil.parseArray(ShippingData);
                Gson gson = new GsonBuilder().serializeNulls().create();
                List <IndexQuery> queries = new ArrayList <IndexQuery>();
                for (int i = 0; i < ShipArray.size(); i++) {
                    IndexQuery indexQuery = new IndexQuery();
                    JSONObject jsonObject = (JSONObject) ShipArray.get(i);
                    indexQuery.setSource("");
                    //计算点 相差的距离
                    indexQuery.setSource(gson.toJson(getTgRadarEntity(jsonObject)));
                    indexQuery.setIndexName(RADAR_NAME);
                    indexQuery.setType(TYPE);
                    queries.add(indexQuery);

                    if (counter % 500 == 0) {
                        log.info("历史数据库提交数据条数 : " + counter);
                        elasticsearchTemplate.bulkIndex(queries);
                        queries.clear();
                    }
                    counter++;
                }
                //不足批的索引最后不要忘记提交
                if (queries.size() > 0) {
                    elasticsearchTemplate.bulkIndex(queries);
                }
                elasticsearchTemplate.refresh(RADAR_NAME);
                log.info("历史数据提交完成.");
            }
        } catch (Exception e) {
            log.info("IndexerService.bulkIndex e;" + e.getMessage());
            throw e;
        }
        return -1;
    }

    public long TagetChangesSave(String ShippingData){
        Integer counter = 0;
        try {
            if (!elasticsearchTemplate.indexExists(TARGETCHANGES)) {
                elasticsearchTemplate.createIndex(TARGETCHANGES, TargetChanges.class);
            }
            if (!ShippingData.equals("")) {
                //解析船只数据
                JSONArray ShipArray = JSONUtil.parseArray(ShippingData);
                Gson gson = new GsonBuilder().serializeNulls().create();
                List <IndexQuery> queries = new ArrayList <IndexQuery>();
                for (int i = 0; i < ShipArray.size(); i++) {
                    IndexQuery indexQuery = new IndexQuery();
                    JSONObject jsonObject = (JSONObject) ShipArray.get(i);
                    TargetChanges targetChanges=getTargetChangesEntity(jsonObject);
                    if(targetChanges.getAlarmset()!=null){
                        indexQuery.setSource("");
                        indexQuery.setSource(gson.toJson(targetChanges));
                        indexQuery.setIndexName(TARGETCHANGES);
                        indexQuery.setType(TYPE);
                        queries.add(indexQuery);
                    }

                    if (queries.size() % 500 == 0) {
                        if(queries.size()!=0){
                            elasticsearchTemplate.bulkIndex(queries);
                            queries.clear();
                            log.info("bulkIndex counter : " + queries.size());
                        }
                    }
                    counter++;
                }
                //不足批的索引最后不要忘记提交
                if (queries.size() > 0) {
                    elasticsearchTemplate.bulkIndex(queries);
                }
//                Shipping.write("C:\\Users\\Administrator\\Desktop\\123123\\全部数据" + ".json",gson.toJson(queries));
                elasticsearchTemplate.refresh(TARGETCHANGES);
                log.info("bulkIndex completed..."+ queries.size());
            }
        } catch (Exception e) {
            log.info("IndexerService.bulkIndex e;" + e.getMessage());
            throw e;
        }
        return -1;
    }

//    public boolean deleData(JSONObject jsonObject){
//        Double lan = jsonObject.getDouble("latitude");
//        Double lon = jsonObject.getDouble("longitude");
//        if (eventTable.containsKey(key)) {
//
//        }
//        return null;
//    }


    /**
     * 处理历史数据字段
     * @param jsonObject
     * @return
     */
    public TgRadarMove getTgRadarEntity(JSONObject jsonObject) {
        TgRadarMove tgRadarMove = new TgRadarMove();
        Double lan = jsonObject.getDouble("latitude");
        Double lon = jsonObject.getDouble("longitude");

        if (jsonObject.containsKey("aisLength")) {
            tgRadarMove.setAislength(jsonObject.getDouble("aisLength"));
        } else {
            tgRadarMove.setAislength(null);
        }

        if (jsonObject.containsKey("direction")) {
            tgRadarMove.setDirection(jsonObject.getDouble("direction"));
        } else {
            tgRadarMove.setDirection(null);
        }

        if (jsonObject.containsKey("length")) {
            tgRadarMove.setLength(jsonObject.getDouble("length"));
        } else {
            tgRadarMove.setLength(null);
        }

        if (jsonObject.containsKey("maxLength")) {
            tgRadarMove.setMaxlength(jsonObject.getDouble("maxLength"));
        } else {
            tgRadarMove.setMaxlength(null);
        }

        if (jsonObject.containsKey("mmsi")) {
            tgRadarMove.setMmsi(jsonObject.getInt("mmsi"));
        } else {
            tgRadarMove.setMmsi(null);
        }

        if (jsonObject.containsKey("quality")) {
            tgRadarMove.setQuality(jsonObject.getDouble("quality"));
        } else {
            tgRadarMove.setQuality(null);
        }

        if (jsonObject.containsKey("radarids")) {
            tgRadarMove.setQuality(jsonObject.getDouble("radar"));
        } else {
            tgRadarMove.setQuality(null);
        }

        if (jsonObject.containsKey("ship_belong")) {
            tgRadarMove.setShip_belong(jsonObject.getStr("ship_belong"));
        } else {
            tgRadarMove.setShip_belong(null);
        }

        if (jsonObject.containsKey("ship_class")) {
            tgRadarMove.setShip_class(jsonObject.getShort("ship_class"));
        } else {
            tgRadarMove.setShip_class(null);
        }

        if (jsonObject.containsKey("speed")) {
            tgRadarMove.setSpeed(jsonObject.getDouble("speed"));
        } else {
            tgRadarMove.setSpeed(null);
        }

        if (jsonObject.containsKey("target_id")) {
            tgRadarMove.setTarget_id(Long.valueOf(jsonObject.getStr("ship_belong") + jsonObject.getStr("target_id")));
        } else {
            tgRadarMove.setTarget_id(null);
        }

        if (jsonObject.containsKey("target_name")) {
            tgRadarMove.setTarget_name(jsonObject.getStr("target_name"));
        } else {
            tgRadarMove.setTarget_name(null);
        }

        if (jsonObject.containsKey("timestamp")) {
            Long timestamp = DateUtil.parse(jsonObject.getStr("timestamp")).getTime();
            tgRadarMove.setTimestamp(timestamp);
        } else {
            tgRadarMove.setTimestamp(null);
        }

        if (jsonObject.containsKey("Nationality")) {
            tgRadarMove.setNationality(jsonObject.getStr("Nationality"));
        } else {
            tgRadarMove.setNationality(null);
        }

        if (jsonObject.containsKey("ShipType")) {
            tgRadarMove.setShiptype(jsonObject.getStr("ShipType"));
        } else {
            tgRadarMove.setShiptype(null);
        }

        if (jsonObject.containsKey("Wide")) {
            tgRadarMove.setWide(jsonObject.getDouble("Wide"));
        } else {
            tgRadarMove.setWide(null);
        }

        if (jsonObject.containsKey("AISReceiver")) {
            tgRadarMove.setAisreceiver(jsonObject.getStr("AISReceiver"));
        } else {
            tgRadarMove.setAisreceiver(null);
        }

        if (jsonObject.containsKey("imo")) {
            tgRadarMove.setImo(jsonObject.getStr("imo"));
        } else {
            tgRadarMove.setImo(null);
        }

        if (jsonObject.containsKey("CallSign")) {
            tgRadarMove.setCallsign(jsonObject.getStr("CallSign"));
        } else {
            tgRadarMove.setCallsign(null);
        }

        if (jsonObject.containsKey("course")) {
            tgRadarMove.setCourse(jsonObject.getStr("course"));
        } else {
            tgRadarMove.setCourse(null);
        }

        if (jsonObject.containsKey("displayId")) {
            tgRadarMove.setDisplayid(jsonObject.getInt("displayId"));
        } else {
            tgRadarMove.setDisplayid(null);
        }

        GeoPoint geoPoint = new GeoPoint(lan, lon);
        tgRadarMove.setGeometry(geoPoint);

        if (jsonObject.containsKey("duration")) {
            DecimalFormat df = new DecimalFormat(".00");
            tgRadarMove.setDuration(Double.valueOf(df.format(jsonObject.getDouble("duration"))));
        } else {
            tgRadarMove.setDuration(null);
        }

        return tgRadarMove;
    }

    /**
     * 处理目标变化表的数据
     * @param jsonObject
     * @return
     */
    public TargetChanges getTargetChangesEntity(JSONObject jsonObject) {
        TargetChanges targetChanges = new TargetChanges();
        Double lan = jsonObject.getDouble("latitude");
        Double lon = jsonObject.getDouble("longitude");

        if (jsonObject.containsKey("aisLength")) {
            targetChanges.setAislength(jsonObject.getDouble("aisLength"));
        } else {
            targetChanges.setAislength(null);
        }

        if (jsonObject.containsKey("direction")) {
            targetChanges.setDirection(jsonObject.getDouble("direction"));
        } else {
            targetChanges.setDirection(null);
        }

        if (jsonObject.containsKey("length")) {
            targetChanges.setLength(jsonObject.getDouble("length"));
        } else {
            targetChanges.setLength(null);
        }

        if (jsonObject.containsKey("maxLength")) {
            targetChanges.setMaxlength(jsonObject.getDouble("maxLength"));
        } else {
            targetChanges.setMaxlength(null);
        }

        if (jsonObject.containsKey("mmsi")) {
            targetChanges.setMmsi(jsonObject.getInt("mmsi"));
        } else {
            targetChanges.setMmsi(null);
        }

        if (jsonObject.containsKey("quality")) {
            targetChanges.setQuality(jsonObject.getDouble("quality"));
        } else {
            targetChanges.setQuality(null);
        }

        if (jsonObject.containsKey("radarids")) {
            targetChanges.setQuality(jsonObject.getDouble("radar"));
        } else {
            targetChanges.setQuality(null);
        }

        if (jsonObject.containsKey("ship_belong")) {
            targetChanges.setShip_belong(jsonObject.getStr("ship_belong"));
        } else {
            targetChanges.setShip_belong(null);
        }

        if (jsonObject.containsKey("ship_class")) {
            targetChanges.setShip_class(jsonObject.getShort("ship_class"));
        } else {
            targetChanges.setShip_class(null);
        }

        if (jsonObject.containsKey("speed")) {
            targetChanges.setSpeed(jsonObject.getDouble("speed"));
        } else {
            targetChanges.setSpeed(null);
        }

        if (jsonObject.containsKey("target_id")) {
            targetChanges.setTarget_id(Long.valueOf(jsonObject.getStr("ship_belong") + jsonObject.getStr("target_id")));
        } else {
            targetChanges.setTarget_id(null);
        }

        if (jsonObject.containsKey("target_name")) {
            targetChanges.setTarget_name(jsonObject.getStr("target_name"));
        } else {
            targetChanges.setTarget_name(null);
        }

        if (jsonObject.containsKey("timestamp")) {
            Long timestamp = DateUtil.parse(jsonObject.getStr("timestamp")).getTime();
            targetChanges.setTimestamp(timestamp);
        } else {
            targetChanges.setTimestamp(null);
        }

        if (jsonObject.containsKey("Nationality")) {
            targetChanges.setNationality(jsonObject.getStr("Nationality"));
        } else {
            targetChanges.setNationality(null);
        }

        if (jsonObject.containsKey("ShipType")) {
            targetChanges.setShiptype(jsonObject.getStr("ShipType"));
        } else {
            targetChanges.setShiptype(null);
        }

        if (jsonObject.containsKey("Wide")) {
            targetChanges.setWide(jsonObject.getDouble("Wide"));
        } else {
            targetChanges.setWide(null);
        }

        if (jsonObject.containsKey("AISReceiver")) {
            targetChanges.setAisreceiver(jsonObject.getStr("AISReceiver"));
        } else {
            targetChanges.setAisreceiver(null);
        }

        if (jsonObject.containsKey("imo")) {
            targetChanges.setImo(jsonObject.getStr("imo"));
        } else {
            targetChanges.setImo(null);
        }

        if (jsonObject.containsKey("CallSign")) {
            targetChanges.setCallsign(jsonObject.getStr("CallSign"));
        } else {
            targetChanges.setCallsign(null);
        }

        if (jsonObject.containsKey("course")) {
            targetChanges.setCourse(jsonObject.getStr("course"));
        } else {
            targetChanges.setCourse(null);
        }

        if (jsonObject.containsKey("displayId")) {
            targetChanges.setDisplayid(jsonObject.getInt("displayId"));
        } else {
            targetChanges.setDisplayid(null);
        }
        GeoPoint geoPoint = new GeoPoint(lan, lon);
        targetChanges.setGeometry(geoPoint);

        TargetChanges res=process(targetChanges);
        if(res!=null){
            targetChanges.setAlarmset(res.getAlarmset());
        }else {
            targetChanges.setAlarmset(null);
        }
        targetChanges.setAddtime(DateTime.now().getTime());
        return targetChanges;
    }


    public String getRadarName() {
        Date date = new Date();
        Integer year = DateUtil.year(date);
        String month = String.valueOf(DateUtil.month(date) + 1);
        if (month.length() == 1) {
            month = "0" + month;
        }
        return "his_" + year + "_" + month;
    }

    public TargetChanges process(TargetChanges targetChanges) {
        TargetChanges ret = null;
        Object lastValue, currValue;
        try {
            String key = String.valueOf(targetChanges.getTarget_id());
            Date now = new Date();
            if (eventTable.containsKey(key)) {
                item = eventTable.get(key);
                lastValue = item.getMmsi();
                currValue = targetChanges.getMmsi();
                if (lastValue == null && currValue != null) {
                    //打开
                    ret = outGeoEvent(targetChanges, "3");
                } else if (lastValue != null && currValue == null) {
                    //关闭
                    ret = outGeoEvent(targetChanges, "4");
                } else if (lastValue != null && currValue != null && !lastValue.toString().equals(currValue.toString())) {
                    //套用
                    ret = outGeoEvent(targetChanges, "5");
                }
                //处理丢失
                if ((ret == null && eventTable.size() > Cache_Size)) {
                    entrys = eventTable.entrySet().iterator();
                    while (entrys.hasNext()) {
                        item = entrys.next().getValue();
                        Date date = new Date(item.getTimestamp());
                        calendar.setTime(date);
                        calendar.add(Calendar.SECOND, Time_Second);
                        if (now.after(calendar.getTime())) {
                            entrys.remove();
                            //TODO处理将之前的点连成线
                            ret = outGeoEvent(item, "2");
                            break;
                        }
                    }
                }
                eventTable.remove(key);
                eventTable.put(key, targetChanges);
            }
            //新增目标
            else {
                ret = outGeoEvent(targetChanges, "1");
                eventTable.put(key, ret);
            }
        } catch (Exception err) {
            log.error(err.getMessage());
            ret = null;
        }
        return ret;
    }

    private TargetChanges outGeoEvent(TargetChanges targetChanges, String s) {
        TargetChanges ret = null;
        try {
            if (targetChanges != null) {
                targetChanges.setAlarmset(s);
                ret = targetChanges;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            ret = null;
        }
        return ret;

    }

}
